home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / bin / asoundconf < prev    next >
Text File  |  2008-09-25  |  11KB  |  459 lines

  1. #!/usr/bin/python
  2.  
  3. # (C) 2005 Canonical Ltd.
  4. # Author: Martin Pitt <martin.pitt@ubuntu.com>
  5. # License: GNU General Public License, version 2 or any later version
  6. #
  7. # Modified by: Thomas Hood, Daniel T Chen
  8. #
  9. # Get and set configuration parameters in ~/.asoundrc.asoundconf.
  10.  
  11. import sys, re, os.path
  12.  
  13. our_conf_file = os.path.expanduser('~/.asoundrc.asoundconf')
  14. asoundrc_file = os.path.expanduser('~/.asoundrc')
  15. predefs_file = '/usr/share/alsa/alsa.conf'
  16.  
  17. setting_re_template = '!?\s*%s\s*(?:=|\s)\s*([^;,]+)[;,]?$'
  18.  
  19. our_conf_header = '''# ALSA library configuration file managed by asoundconf(1).
  20. #
  21. # MANUAL CHANGES TO THIS FILE WILL BE OVERWRITTEN!
  22. #
  23. # Manual changes to the ALSA library configuration should be implemented
  24. # by editing the ~/.asoundrc file, not by editing this file.
  25. '''
  26.  
  27. asoundrc_header = '''# ALSA library configuration file
  28. '''
  29.  
  30. inclusion_comment = '''# Include settings that are under the control of asoundconf(1).
  31. # (To disable these settings, comment out this line.)'''
  32.  
  33. usage = '''Usage:
  34. asoundconf is-active
  35. asoundconf get|delete PARAMETER
  36. asoundconf set PARAMETER VALUE
  37. asoundconf list
  38.  
  39. Convenience macro functions:
  40. asoundconf set-default-card PARAMETER
  41. asoundconf reset-default-card
  42. asoundconf set-pulseaudio
  43. asoundconf unset-pulseaudio
  44. asoundconf set-oss PARAMETER
  45. asoundconf unset-oss
  46. '''
  47.  
  48.  
  49. needs_default_card = '''You have omitted a necessary parameter.  Please see the output from `asoundconf list`, and use one of those sound card(s) as the parameter.
  50. '''
  51.  
  52.  
  53. needs_oss_dev = '''You have omitted a necessary parameter.  Please specify an OSS device (e.g., /dev/dsp).
  54. '''
  55.  
  56.  
  57. superuser_warn = '''Please note that you are attempting to run asoundconf as a privileged superuser, which may have unintended consequences.
  58. '''
  59.  
  60.  
  61. def get_default_predefs():
  62.     try:
  63.     if not os.path.exists(predefs_file):
  64.         return
  65.     predefs_file_entire = open(predefs_file).readlines()
  66.     r = re.compile('^defaults')
  67.     ## Between these hashes, add additional unique regexps that
  68.     ## must exist at the end of the user's custom asoundrc.
  69.     s = re.compile('^defaults.namehint')
  70.     ##
  71.     predefs_list = []
  72.     must_append_predefs_list = []
  73.     for i in predefs_file_entire:
  74.         if r.match(i) and not s.match(i):
  75.         predefs_list.append(str(i).strip())
  76.         elif s.match(i):
  77.         must_append_predefs_list.append(str(i).strip())
  78.     for i in must_append_predefs_list:
  79.         predefs_list.append(str(i).strip())
  80.     return predefs_list
  81.     except IOError:
  82.     pass
  83.  
  84.  
  85. def ensure_our_conf_exists():
  86.     '''If it does not exist then generate a default configuration
  87.     file with no settings.
  88.  
  89.     Return: True on success, False if the file could not be created.
  90.     '''
  91.  
  92.     if os.path.exists(our_conf_file):
  93.         return True
  94.  
  95.     try:
  96.         open(our_conf_file, 'w').write(our_conf_header)
  97.         return True
  98.     except IOError:
  99.         print >> sys.stderr, 'Error: could not create', our_conf_file
  100.         return False
  101.  
  102.  
  103. def ensure_asound_rc_exists():
  104.     '''Generate a default user configuration file with only the
  105.     inclusion line.
  106.  
  107.     Return: True on success, False if the file could not be created.
  108.     '''
  109.  
  110.     if os.path.exists(asoundrc_file):
  111.         return True
  112.  
  113.     try:
  114.         open(asoundrc_file, 'w').write('%s\n%s\n<%s>\n\n' % (asoundrc_header, inclusion_comment, our_conf_file))
  115.         return True
  116.     except IOError:
  117.         print >> sys.stderr, 'Error: could not create', asoundrc_file
  118.         return False
  119.  
  120.  
  121. def sds_transition():
  122.     '''Replace the magic comments added to the user configuration file
  123.     by the obsolete set-default-soundcard program with the standard
  124.     inclusion statement for our configuration file.
  125.     '''
  126.  
  127.     if not os.path.exists(asoundrc_file):
  128.         return
  129.  
  130.     lines = open(asoundrc_file).readlines()
  131.  
  132.     start_marker_re = re.compile('### BEGIN set-default-soundcard')
  133.     end_marker_re = re.compile('### END set-default-soundcard')
  134.  
  135.     userconf_lines = []
  136.     our_conf_lines = []
  137.  
  138.     # read up to start comment
  139.     lineno = 0
  140.     found = 0
  141.     for l in lines:
  142.         lineno = lineno+1
  143.         if start_marker_re.match(l):
  144.             found = 1
  145.             break
  146.         userconf_lines.append(l)
  147.  
  148.     if found:
  149.         # replace magic comment section with include
  150.         userconf_lines.append('%s\n<%s>\n\n' % (inclusion_comment, our_conf_file))
  151.     else:
  152.         # no magic comment
  153.         return
  154.  
  155.     # read magic comment section until end marker and add it to asoundconf
  156.     found = 0
  157.     for l in lines[lineno:]:
  158.         lineno = lineno+1
  159.         if end_marker_re.match(l):
  160.             found = 1
  161.             break
  162.         if not l.startswith('#'):
  163.             our_conf_lines.append(l)
  164.  
  165.     if not found:
  166.         # no complete magic comment
  167.         return
  168.  
  169.     # add the rest to user conf
  170.     userconf_lines = userconf_lines + lines[lineno:]
  171.  
  172.     # write our configuration file
  173.     if not ensure_our_conf_exists():
  174.         return
  175.     try:
  176.         open(our_conf_file, 'a').writelines(our_conf_lines)
  177.     except IOError:
  178.         return # panic out
  179.  
  180.     # write user configuration file
  181.     try:
  182.         open(asoundrc_file, 'w').writelines(userconf_lines)
  183.     except IOError:
  184.         pass
  185.  
  186.  
  187. def is_active():
  188.     '''Check that the user configuration file is either absent, or,
  189.     if present, that it includifies the asoundconf configuration file;
  190.     in those cases asoundconf can be used to change the user's ALSA
  191.     library configuration.
  192.  
  193.     Also transition from the legacy set-default-soundcard program.
  194.  
  195.     Return True if the above condition is met, False if not.
  196.     '''
  197.  
  198.     if not os.path.exists(asoundrc_file):
  199.         return True
  200.  
  201.     sds_transition()
  202.  
  203.     # check whether or not the file has the inclusion line
  204.     include_re = re.compile('\s*<\s*%s\s*>' % our_conf_file)
  205.     for l in open(asoundrc_file):
  206.         if include_re.match(l):
  207.             return True
  208.  
  209.     return False
  210.  
  211. def get(prmtr):
  212.     '''Print the value of the given parameter on stdout
  213.  
  214.     Also transition from the legacy set-default-soundcard program.
  215.  
  216.     Return True on success, and False if the value is not set.
  217.     '''
  218.  
  219.     sds_transition()
  220.  
  221.     if not os.path.exists(our_conf_file):
  222.         return False
  223.  
  224.     setting_re = re.compile(setting_re_template % prmtr)
  225.  
  226.     try:
  227.         for line in open(our_conf_file):
  228.             m = setting_re.match(line)
  229.             if m:
  230.                 print m.group(1).strip()
  231.                 return True
  232.         return False
  233.     except IOError:
  234.         return False
  235.  
  236. def list():
  237.     '''Get card names from /proc/asound/cards'''
  238.  
  239.     cardspath = '/proc/asound/cards'
  240.     if not os.path.exists(cardspath):
  241.         return False
  242.     procfile = open(cardspath, 'rb')
  243.     cardline = re.compile('^\s*\d+\s*\[')
  244.     card_lines = []
  245.     lines = procfile.readlines()
  246.     for l in lines:
  247.         if cardline.match(l):
  248.             card_lines.append(re.sub(r'^\s*\d+\s*\[(\w+)\s*\].+','\\1',l))
  249.     print "Names of available sound cards:"
  250.     for cardname in card_lines:
  251.         print cardname.strip()
  252.     return True
  253.  
  254. def delete(prmtr):
  255.     '''Delete the given parameter.
  256.  
  257.     Also transition from the legacy set-default-soundcard program.
  258.  
  259.     Return True on success, and False on an error.
  260.     '''
  261.  
  262.     sds_transition()
  263.  
  264.     if not os.path.exists(our_conf_file):
  265.         return False
  266.  
  267.     setting_re = re.compile(setting_re_template % prmtr)
  268.     lines = []
  269.     try:
  270.         lines = open(our_conf_file).readlines()
  271.     except IOError:
  272.         return False
  273.  
  274.     found = 0
  275.     for i in xrange(len(lines)):
  276.         if setting_re.match(lines[i]):
  277.             del lines[i]
  278.             found = 1
  279.             break
  280.  
  281.     if found:
  282.         # write back file
  283.         try:
  284.             f = open(our_conf_file, 'w')
  285.         except IOError:
  286.             return False
  287.         f.writelines(lines)
  288.  
  289.     return True
  290.  
  291.  
  292. def set(prmtr, value):
  293.     '''Set the given parameter to the given value
  294.  
  295.     Also transition from the legacy set-default-soundcard program.
  296.  
  297.     Return True on success, and False on an error.
  298.     '''
  299.  
  300.     sds_transition()
  301.  
  302.     setting_re = re.compile(setting_re_template % prmtr)
  303.     lines = []
  304.  
  305.     ensure_asound_rc_exists()
  306.     # N.B. We continue even if asoundrc could not be created
  307.     # and we do NOT ensure that our configuration is "active"
  308.  
  309.     if not ensure_our_conf_exists():
  310.         return False
  311.  
  312.     try:
  313.         lines = open(our_conf_file).readlines()
  314.     except IOError:
  315.         return False
  316.  
  317.     newsetting = '%s %s\n' % (prmtr, value)
  318.  
  319.     # if setting is already present, change it
  320.     found = 0
  321.     for i in xrange(len(lines)):
  322.         if setting_re.match(lines[i]):
  323.             lines[i] = newsetting
  324.             found = 1
  325.             break
  326.  
  327.     if not found:
  328.         lines.append(newsetting)
  329.  
  330.     # write back file
  331.     try:
  332.         f = open(our_conf_file, 'w')
  333.     except IOError:
  334.         return False
  335.     f.writelines(lines)
  336.     return True
  337.  
  338. def set_default_card(card):
  339.     clist = get_default_predefs()
  340.     sep = re.compile('\s+')
  341.     r = re.compile('^defaults.pcm.card')
  342.     s = re.compile('^defaults.ctl.card')
  343.     ## !defaults.pcm.card and defaults.ctl.card should lead
  344.     ## the user's custom asoundrc.
  345.     if set('!defaults.pcm.card', card) and \
  346.        set('defaults.ctl.card', card):
  347.         for i in clist:
  348.         (j, k) = sep.split(i)
  349.         if not r.match(j) and not s.match(j):
  350.             if not set(j, k):
  351.             return False
  352.         return True
  353.     else:
  354.         return False
  355.  
  356. def reset_default_card():
  357.     clist = get_default_predefs()
  358.     sep = re.compile('\s+')
  359.     for i in clist:
  360.         (j, k) = sep.split(i)
  361.         if not delete(j):
  362.         return False
  363.     return True
  364.  
  365. def delete_pcm_default():
  366.     return delete('pcm.!default')
  367.  
  368. def delete_ctl_default():
  369.     return delete('ctl.!default')
  370.  
  371. def set_pulseaudio():
  372.     return set('pcm.!default', '{ type pulse }') and \
  373.     set('ctl.!default', '{ type pulse }')
  374.  
  375. def unset_pulseaudio():
  376.     return delete_pcm_default() and \
  377.     delete_ctl_default()
  378.  
  379. def set_oss(device):
  380.     endbrace = ' }'
  381.     return set('pcm.!default { type oss  device', device + endbrace)
  382.  
  383. def unset_oss():
  384.     return delete_pcm_default()
  385.  
  386. def exit_code(result):
  387.     '''Exit program with code 0 if result is True, otherwise exit with code
  388.     1.
  389.     '''
  390.  
  391.     if result:
  392.         sys.exit(0)
  393.     else:
  394.         sys.exit(1)
  395.  
  396.  
  397. ##
  398. ## main
  399. ##
  400.  
  401. if os.geteuid() == 0:
  402.     print superuser_warn
  403.  
  404. if len(sys.argv) < 2 or sys.argv[1] == '--help' or sys.argv[1] == '-h':
  405.     print usage
  406.     sys.exit(0)
  407.  
  408. if sys.argv[1] == 'is-active':
  409.     exit_code(is_active())
  410.  
  411. if sys.argv[1] == 'get':
  412.     if len(sys.argv) != 3:
  413.         print usage
  414.         sys.exit(1)
  415.     exit_code(get(sys.argv[2]))
  416.  
  417. if sys.argv[1] == 'delete':
  418.     if len(sys.argv) != 3:
  419.         print usage
  420.         sys.exit(1)
  421.     exit_code(delete(sys.argv[2]))
  422.  
  423. if sys.argv[1] == 'set':
  424.     if len(sys.argv) != 4:
  425.         print usage
  426.         sys.exit(1)
  427.     exit_code(set(sys.argv[2], sys.argv[3]))
  428.  
  429. if sys.argv[1] == 'list':
  430.     exit_code(list())
  431.  
  432. if sys.argv[1] == 'set-default-card':
  433.     if len(sys.argv) != 3:
  434.     print needs_default_card
  435.     sys.exit(1)
  436.     exit_code(set_default_card(sys.argv[2]))
  437.  
  438. if sys.argv[1] == 'reset-default-card':
  439.     exit_code(reset_default_card())
  440.  
  441. if sys.argv[1] == 'set-pulseaudio':
  442.     exit_code(set_pulseaudio())
  443.  
  444. if sys.argv[1] == 'unset-pulseaudio':
  445.     exit_code(unset_pulseaudio())
  446.  
  447. if sys.argv[1] == 'set-oss':
  448.     if len(sys.argv) != 3:
  449.     print needs_oss_dev
  450.     sys.exit(1)
  451.     exit_code(set_oss(sys.argv[2]))
  452.  
  453. if sys.argv[1] == 'unset-oss':
  454.     exit_code(unset_oss())
  455.  
  456. print usage
  457. sys.exit(1)
  458.  
  459.